﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RoboRace_Shared
{
    public enum DIRECTION { FORWARD = 0, BACKWARD }
    public enum COMPASS { NORTH = 0, EAST, SOUTH, WEST }
    public enum ROTATION { LEFT = 0, RIGHT, NONE }
    public enum ACTION { MOVE = 0, ROTATE }

    public interface IRobot
    {
        string Name { get; }
        Boolean IsDead { get; }
        COMPASS IsPointing { get; }
        Coordinate Coordinate { get; set; }
        int Damage { get; }
        Guid PlayerGuid { get; }

        void Hit();
        void Hit(int damage);
        void Repair();
        void Repair(int repairAmt);
        void Move(Coordinate newCoord);
        void Rotate(ROTATION rotation);
        void Die();
        void Spawn();
        void Spawn(Coordinate coordinate, COMPASS pointing);
        void AddRegister();
        void RemoveRegister(int index);
        Boolean LoadRegister(int index, ProgramCard card);
    }

    [Serializable]
    public class Robot : IRobot
    {
        private string _name;
        private Boolean _isDead;
        private int _damage;
        private Coordinate _coordinate;
        private COMPASS _compass;
        private List<Register> _registers;
        private int _numActiveRegisters;
        private Guid _playerGuid;

        public string Name { get { return _name; } }
        public Boolean IsDead { get { return _isDead; } }
        public COMPASS IsPointing { get { return _compass; } }
        public Coordinate Coordinate { get { return _coordinate; } set { _coordinate = value; } }
        public int Damage { get { return _damage; } }
        public Guid PlayerGuid { get { return _playerGuid; } }

        public Robot(string name, Guid player)
        {
            if (name != null)
            {
                _name = name;
                _playerGuid = player;
                InitRobot();
            }
        }

        private void InitRobot()
        {
            _coordinate = new Coordinate(0, 0);
            _compass = COMPASS.EAST;
            _isDead = false;
            _damage = 0;

            //Init the registers
            _numActiveRegisters = 5;
            _registers = new List<Register>();
            for (int x = 0; x < _numActiveRegisters; x++)
            {
                _registers.Add(new Register());
            }
        }

        public void Hit()
        {
            if (_damage < 10)
            {
                _damage++;
                if (_damage == 10)
                {
                    Die();
                }
            }

            //Need to check to see if a register needs locked.
        }

        public void Hit(int intAmountDamage)
        {
            if (_damage < 10)
            {
                _damage = _damage + intAmountDamage;
                if (_damage >= 10)
                {
                    Die();
                }
            }
            //Need to check to see if a register needs locked.
        }

        public void Repair()
        {
            if (_damage > 0)
            {
                _damage--;
            }

            //Need to check to see if a register needs unlocked.
        }

        public void Repair(int intAmountRepair)
        {
            if (_damage > 0)
            {
                _damage = _damage + intAmountRepair;
                if (_damage > 10)
                {
                    _damage = 10;
                }
            }

            //Need to check to see if a register needs unlocked.
        }

        public void Move(Coordinate newCoordinate)
        {
            if (newCoordinate != null)
            {
                if ((newCoordinate.X < 0) || (newCoordinate.Y < 0))
                {
                    Die();
                }
                else
                {
                    _coordinate = newCoordinate;
                }
            }
            else
            {
                throw new Exception("Coordinate cannot be null.");
            }
        }

        public void Rotate(ROTATION rotation)
        {
            switch (rotation)
            {
                case ROTATION.LEFT:
                    if (_compass != COMPASS.NORTH)
                    {
                        --_compass;
                    }
                    else
                    {
                        _compass = COMPASS.WEST;
                    }
                    break;
                case ROTATION.RIGHT:
                    if (_compass != COMPASS.WEST)
                    {
                        _compass++;
                    }
                    else
                    {
                        _compass = COMPASS.NORTH;
                    }
                    break;
            }
        }

        public void Die()
        {
            _isDead = true;
        }

        public void Spawn()
        {
            if (_isDead == true)
            {
                InitRobot();
            }
            else
            {
                throw new Exception("You cannot spawn if you are not dead.");
            }
        }

        public void Spawn(Coordinate spawnPoint, COMPASS pointing)
        {
            if (spawnPoint != null)
            {
                if (_isDead == true)
                {
                    InitRobot();
                    _coordinate = spawnPoint;
                    _compass = pointing;
                }
                else
                {
                    throw new Exception("You cannot spawn if you are not dead.");
                }
            }
            else
            {
                throw new ArgumentException("SPAWN Parameters cannot be null");
            }
        }

        public void AddRegister()
        {
            _numActiveRegisters++;
            _registers.Add(new Register());
        }

        public void RemoveRegister(int index)
        {
            _registers.RemoveAt(index);
            _numActiveRegisters--;
        }

        public Boolean LoadRegister(int index, ProgramCard newProgram)
        {
            _registers[index].ActiveCard = newProgram;
            return true;
        }
    }
}
